package com.yanqu.road.server.manager.activity.hsisland;

import com.yanqu.road.entity.activity.hsisland.*;
import com.yanqu.road.entity.activity.hsisland.config.*;
import com.yanqu.road.entity.activity.hsisland.data.*;
import com.yanqu.road.entity.activity.hsisland.enums.*;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.log.cross.hsisland.LogCrossHsIslandBuff;
import com.yanqu.road.entity.log.cross.hsisland.LogCrossHsIslandEnergy;
import com.yanqu.road.entity.log.cross.hsisland.LogCrossHsIslandImageUnlock;
import com.yanqu.road.entity.log.cross.hsisland.LogCrossHsIslandScore;
import com.yanqu.road.entity.player.CrossUserBaseInfo;
import com.yanqu.road.entity.rank.yrank.UserYRank;
import com.yanqu.road.exception.BusinessException;
import com.yanqu.road.pb.activity.HsIslandProto;
import com.yanqu.road.pb.rank.RankProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.hsisland.pb.CrossHsIslandActivityPb;
import com.yanqu.road.server.manager.activity.hsisland.rank.CrossHsIslandRankListModel;
import com.yanqu.road.server.manager.config.GoodsMgr;
import com.yanqu.road.server.manager.log.CrossAutoLogMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.manager.yrank.CrossYRankCacheMgr;
import com.yanqu.road.server.manager.yrank.CrossYRankMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.FixSizeLinkedList;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.energy.EnergyRestoreResult;
import com.yanqu.road.utils.energy.EnergyUtils;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.*;

import static com.yanqu.road.entity.activity.hsisland.enums.HsIslandBattleFieldEnemyEnum.ENEMY_BOSS;
import static com.yanqu.road.entity.activity.hsisland.enums.HsIslandBattleFieldEnemyEnum.ENEMY_MASTER;

public class CrossHsIslandUser {

    /**
     * 玩家数据
     */
    private HsIslandUserData userData;

    /**
     * 玩家日志
     */
    private FixSizeLinkedList<HsIslandUserLog> userLogList;

    /**
     * 打理奖励记录
     */
    private Property autoReward = new Property();

    /**
     * 未领取PVE奖数量（红点用）
     */
    private int pveRewardNum = 0;

    /**
     * 构造
     * @param userData
     */
    public CrossHsIslandUser(HsIslandUserData userData, int logLimit) {
        this.userData = userData;
        this.userLogList = new FixSizeLinkedList<>(logLimit);
    }

    /**
     * 获取配置
     * @return
     */
    public HsIslandConfig getConfig() {
        return CrossHsIslandActivityMgr.getConfig(this.userData.getActivityId(), this.userData.getGroupId());
    }

    /**
     * 获取活动
     * @return
     */
    public CrossHsIslandActivity getActivity() {
        return CrossHsIslandActivityMgr.getActivity(this.userData.getActivityId(), this.userData.getGroupId());
    }

    /**
     * 获取玩家数据
     * @return
     */
    public HsIslandUserData getUserData() {
        return this.userData;
    }

    /**
     * get 未领取PVE奖数量（红点用）
     * @return
     */
    public int getPveRewardNum() {
        return pveRewardNum;
    }

    /**
     * add 未领取PVE奖数量（红点用）
     * @param num
     */
    public synchronized void addPveRewardNum(int num) {
        this.pveRewardNum += num;
    }

    /**
     * 更新战力
     * @param patronsList
     */
    public void updatePower(List<HsIslandPatronsData> patronsList) {
        for (HsIslandPatronsData patronsData : patronsList) {
            HsIslandPatronsData myPatrons = this.userData.getPatronsMap().get(patronsData.getPatronsId());
            if (myPatrons != null) {
                //更新门客战力
                myPatrons.setPower(patronsData.getPower());
            }
        }
        //计算一下总战力
        long power = 0;
        for (HsIslandPatronsData patronsData : this.userData.getPatronsMap().values()) {
            power += patronsData.getPower();
        }
        this.userData.setPower(power);
    }

    /**
     * 玩家积分榜单排名
     */
    public int getUserRank(){
        long userId = this.userData.getUserId();
        int rank = -1;
        CrossUserBaseInfo userBaseInfo = CrossUserMgr.getCrossUserBaseInfo(userId);
        if (userBaseInfo != null) {
            String rankType = String.valueOf(eGamePlayerEventType.HsIslandUserRank.getValue());
//            List<UserYRank> rankList = CrossYRankMgr.getSortUserRankList(this.userData.getActivityId(), this.userData.getGroupId(), rankType);
//            rank = CrossYRankMgr.getUserRankNum(rankList, this.userData.getUserId());
            RankProto.RankListMsg.Builder rankBuilder = CrossYRankCacheMgr.getUserRankList(this.userData.getActivityId(), this.userData.getGroupId(), rankType);
            rank = CrossYRankCacheMgr.getUserRank(this.userData.getActivityId(), this.userData.getGroupId(), rankType, rankBuilder, this.userData.getUserId());
        }
        return rank;
    }

    /**
     * 获取商会
     * @return
     */
    public CrossHsIslandUnion getUnion() {
        return CrossHsIslandActivityMgr.getUnion(this.userData.getActivityId(), this.userData.getGroupId(), this.userData.getUnionId());
    }

    /**
     * 获取玩家所在海域
     * @return
     */
    public CrossHsIslandFloor getFloor() {
        CrossHsIslandUnion union = this.getUnion();
        return union.getFloor(this.userData.getFloorId());
    }

    /**
     * 位置变更
     * @param islandId
     * @param x
     * @param y
     */
    public void changePosition(int islandId, int x, int y) {
        this.userData.setIslandId(islandId);
        this.userData.setX(x);
        this.userData.setY(y);
        //同步海域玩家，我的位置变更了
        CrossHsIslandFloor floor = this.getFloor();
        floor.syncUserChangePosition(this);
        //更新活跃时间
        this.updateActiveTime();
    }

    /**
     * 恢复体力：冷却
     */
    public void energyRestore() {
        HsIslandConfig config = this.getConfig();
        //上次恢复体力时间
        long lastRestoreTime = this.userData.getEnergyRestoreTime();
        //体力CD时间（s）
        int restoreDuration = config.HSISLAND_ENERGY_RECOVER;
        //恢复数量
        int restoreNum = 1;
        //当前体力
        long energy = this.userData.getEnergy();
        //最大体力
        int maxEnergy = config.HSISLAND_ENERGY_MAX;
        //恢复体力
        EnergyRestoreResult energyRestoreResult = EnergyUtils.energyRestore(lastRestoreTime, System.currentTimeMillis(), restoreDuration, restoreNum, maxEnergy, energy);
        long recoverEnergy = energyRestoreResult.getEnergyAfterRestore() - energy;
        //增加体力
        this.userData.setEnergy((int) energyRestoreResult.getEnergyAfterRestore());
        this.userData.setEnergyRestoreTime(energyRestoreResult.getRestoreTime());
        //体力恢复日志
        if (recoverEnergy > 0) {
            LogCrossHsIslandEnergy log = new LogCrossHsIslandEnergy (
                    this.userData.getActivityId(),
                    this.userData.getGroupId(),
                    this.userData.getUnionId(),
                    this.userData.getUserId(),
                    HsIslandLogEnergyTypeEnum.ADD_AUTO.getType(),
                    (int) recoverEnergy,
                    this.userData.getEnergy()
            );
            CrossAutoLogMgr.add(log);
        }
    }

    /**
     * 添加体力-能超上限
     * @param energy
     */
    public synchronized void addEnergy(int energy) {
        //恢复一下
        this.energyRestore();
        this.userData.setEnergy(this.userData.getEnergy() + energy);
    }

    /**
     * 添加体力-不能超上限
     * @param energy
     */
    public synchronized int addEnergyNotFull(int energy) {
        //恢复一下
        this.energyRestore();
        //最大体力
        int maxEnergy = this.getConfig().HSISLAND_ENERGY_MAX;
        if (this.userData.getEnergy() >= maxEnergy) {
            return 0;
        }
        //加上后的体力
        int newEnergy = this.userData.getEnergy() + energy;
        if (newEnergy > maxEnergy) {
            newEnergy = maxEnergy;
        }
        int recoverEnergy = newEnergy - this.userData.getEnergy();//恢复了多少体力
        this.userData.setEnergy(newEnergy);
        return recoverEnergy;
    }

    /**
     * 检查体力是否足够
     * @param reEnergy
     * @return
     */
    public boolean checkEnergyEnough(int reEnergy) {
        //恢复体力
        this.energyRestore();
        //判断玩家体力是否足够
        if (this.userData.getEnergy() >= reEnergy) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 减少体力
     * @param reEnergy
     * @return
     */
    public synchronized boolean reduceEnergy(int reEnergy, HsIslandLogEnergyTypeEnum logEnergyTypeEnum) {
        //检查体力是否充足
        boolean enoughFlag = this.checkEnergyEnough(reEnergy);
        if (enoughFlag) {
            //减少体力
            int newEnergy = this.userData.getEnergy() - reEnergy;
            this.userData.setEnergy(newEnergy);
            //增加【消耗体力，增加协助次数】计数
            this.addUseEnergyAddHelpNumCount(reEnergy);
            //增加【消耗体力，增加可邀请次数】计数
            this.addUseEnergyAddInviteNumCount(reEnergy);
            //全服战意增加
            CrossHsIslandActivity activity = this.getActivity();
            if (activity != null) {
                int addBattleValue = this.getConfig().HSISLAND_HOLY_PILLARS_PLAYER_ADD_PROGRESS * reEnergy;
                activity.addBattleValue(addBattleValue);
            }
            //日志
            LogCrossHsIslandEnergy log = new LogCrossHsIslandEnergy(
                    this.userData.getActivityId(),
                    this.userData.getGroupId(),
                    this.userData.getUnionId(),
                    this.userData.getUserId(),
                    logEnergyTypeEnum.getType(),
                    reEnergy,
                    this.userData.getEnergy()
            );
            CrossAutoLogMgr.add(log);
        }
        return enoughFlag;
    }

    /**
     * 检查体力是否足够-探索
     * @return
     */
    public boolean checkExploreEnergyEnough() {
        //判断是否有BUFF,不需要消耗体力
        if (this.triggerBuffExploreNotEnergy(false)) {
            return true;
        }
        //读取配置，体力消耗值
        int costEnergy = this.getConfig().getExploreEnergyCost(this.userData.getFloorId());
        return this.checkEnergyEnough(costEnergy);
    }

    /**
     * 减少体力：探索
     * @return
     */
    public HsIslandCostEnergyResult exploreReduceEnergy() {
        HsIslandCostEnergyResult result = new HsIslandCostEnergyResult();
        //判断是否有BUFF,不需要消耗体力
        if (this.triggerBuffExploreNotEnergy(true)) {
            result.setCostEnergy(0);
            result.setSuccessFlag(true);
            return result;
        }
        //读取配置，体力消耗值
        int costEnergy = this.getConfig().getExploreEnergyCost(this.userData.getFloorId());
        boolean successFlag = this.reduceEnergy(costEnergy, HsIslandLogEnergyTypeEnum.COST_EXPLORE);
        result.setSuccessFlag(successFlag);
        result.setCostEnergy(costEnergy);
        return result;
    }

    /**
     * 消耗协助次数
     * @return
     */
    public synchronized boolean costHelpNum(int num) {
        if (this.userData.getHelpNum() <= 0) {
            return false;
        }
        if (this.userData.getHelpNum() < num) {
            return false;
        }
        this.userData.setHelpNum(this.userData.getHelpNum() - num);
        return true;
    }

    /**
     * 增加【每消耗N1体力恢复N2协助次数】计数
     *
     * @param energyNum
     */
    public void addUseEnergyAddHelpNumCount(int energyNum) {
        //读取配置【每消耗N1体力恢复N2协助次数】
        int useEnergyNum = this.getConfig().HSISLAND_PVE_ASSIST_TIMES_RECOVER;
        int addHelpNum = 1;
        //新计数
        int newUseEnergyAddHelpNumCount = this.userData.getHelpNumCount() + energyNum;
        //判断是否足够增加协助次数
        if (newUseEnergyAddHelpNumCount >= useEnergyNum) {
            newUseEnergyAddHelpNumCount = newUseEnergyAddHelpNumCount - useEnergyNum;
            //增加协助次数
            this.userData.setHelpNum(this.userData.getHelpNum() + addHelpNum);
        }
        this.userData.setHelpNumCount(newUseEnergyAddHelpNumCount);
    }

    /**
     * 增加【每消耗N1体力恢复N2邀请次数】计数
     *
     * @param energyNum
     */
    public void addUseEnergyAddInviteNumCount(int energyNum) {
        //读取配置【每消耗N1体力恢复N2邀请次数】
        int useEnergyNum = this.getConfig().HSISLAND_PVE_INVITE_TIMES_RECOVER;
        int addInviteNum = 1;
        //新计数
        int newCount = this.userData.getCanPveInviteNumCount() + energyNum;
        //判断是否足够增加邀请次数
        if (newCount >= useEnergyNum) {
            newCount = newCount - useEnergyNum;
            //增加协助次数
            this.userData.setCanPveInviteNum(this.userData.getCanPveInviteNum() + addInviteNum);
        }
        this.userData.setCanPveInviteNumCount(newCount);
    }

    /**
     * 使用道具恢复体力
     * @param num
     * @throws BusinessException
     */
    public void usePropRecoverEnergy(int num) throws BusinessException {
        int propId = this.getConfig().HSISLAND_ENERGY_ITEM_ID;
        GoodsInfo goodsInfo = GoodsMgr.getGoodsInfo(propId);
        if (goodsInfo == null) {
            throw new BusinessException(GameErrorCode.E_GOODS_NO_EXIST);
        }
        //获取增加的体力值
        int oneAddEnergy = goodsInfo.getParamList().get(0).intValue();
        int addEnergy = oneAddEnergy * num;
        this.addEnergy(addEnergy);
        //日志
        LogCrossHsIslandEnergy log = new LogCrossHsIslandEnergy (
                this.userData.getActivityId(),
                this.userData.getGroupId(),
                this.userData.getUnionId(),
                this.userData.getUserId(),
                HsIslandLogEnergyTypeEnum.ADD_PROP.getType(),
                addEnergy,
                this.userData.getEnergy()
        );
        CrossAutoLogMgr.add(log);
    }

    /**
     * 减少可邀请次数
     */
    public synchronized void costICanPveInviteNum() {
        this.userData.setCanPveInviteNum(this.userData.getCanPveInviteNum() - 1);
    }

    /**
     * 获取积分加成
     * @return
     */
    public int getScoreAddRate() {
        int addRate = 0;
//        //需求变更，形象不加成，形象积分加成
//        if (this.userData.getUnlockedImageIds().contains(HsIslandImageIdEnum.IMAGE_ADD_SCORE.getType())) {
//            addRate += this.getImageAddScoreRate();
//        }
        return addRate;
    }

    /**
     * 获取形象积分加成
     * @return
     */
    public int getImageAddScoreRate() {
        int addRate = 0;
        GoodsInfo goodsInfo = GoodsMgr.getGoodsInfo(HsIslandImageIdEnum.IMAGE_ADD_SCORE.getType());
        if (goodsInfo != null) {
            addRate = goodsInfo.getParamList().get(1).intValue();
        }
        return addRate;
    }

    /**
     * 计算加成后的积分
     * @param score
     * @param addRate
     * @return
     */
    public long countScore(long score, int addRate) {
        long addScore = BigDecimal.valueOf(score).multiply(BigDecimal.valueOf(addRate).divide(BigDecimal.valueOf(1000), 8,  RoundingMode.UP)).setScale(0, RoundingMode.CEILING).longValue();
        return score + addScore;
    }

    /**
     * 添加积分
     * @param addScore
     */
    public void addScore(long addScore) {
        if (addScore > 0) {
            //积分加成
            long finalAddScore = this.countScore(addScore, this.getScoreAddRate());
            this.userData.addScore(finalAddScore);
            //榜单变更
            this.changeUserRank();
            //通知区服,更新成就condition
            HsIslandProto.HsIslandConditionChangeFromCrossMsg.Builder msg = HsIslandProto.HsIslandConditionChangeFromCrossMsg.newBuilder();
            msg.setActivityId(this.userData.getActivityId());
            msg.setConditionType(eGamePlayerEventType.HsIslandUserAchievement.getValue());
            msg.setValue(this.userData.getScore());
            msg.setParam("");
            MessageHelper.sendPacket(this.userData.getServerId(), this.userData.getUserId(), YanQuMessageUtils.buildMessage(Protocol.S_HS_ISLAND_CONDITION_CHANGE_FROM_CROSS, msg));
            //基金分变更
            CrossHsIslandUnion union = this.getUnion();
            long unionScore = 0;
            if (union != null) {
                union.syncFundScoreChange();
                unionScore = union.getUnionScore();
            }
            //日志
            LogCrossHsIslandScore log = new LogCrossHsIslandScore(
                    this.userData.getActivityId(),
                    this.userData.getGroupId(),
                    this.userData.getUnionId(),
                    this.userData.getUserId(),
                    finalAddScore,
                    this.userData.getScore(),
                    unionScore
            );
            CrossAutoLogMgr.add(log);
        }
    }

    /**
     * 个人积分榜变更
     */
    public void changeUserRank(){
        UserYRank userYRank = new UserYRank();
        userYRank.setUserId(this.userData.getUserId());
        userYRank.setActivityId(this.userData.getActivityId());
        userYRank.setGroupId(this.userData.getGroupId());
        userYRank.setIdKey(String.valueOf(eGamePlayerEventType.HsIslandUserRank.getValue()));
        userYRank.setValue(BigInteger.valueOf(this.userData.getScore()));
        userYRank.setUpdateTime(System.currentTimeMillis());
        userYRank.setUserBaseInfo(CrossUserMgr.getUserBaseInfo(this.userData.getUserId()));
        CrossYRankMgr.userRankChange(userYRank);
    }

    /**
     * 同步玩家数据
     */
    public void syncUserData() {
        HsIslandProto.HsIslandSyncUserDataMsg.Builder builder = HsIslandProto.HsIslandSyncUserDataMsg.newBuilder();
        builder.setUserData(CrossHsIslandActivityPb.buildHsIslandUserData(this));
        MessageHelper.sendPacket(this.userData.getServerId(), this.userData.getUserId(), YanQuMessageUtils.buildMessage(Protocol.U_HS_ISLAND_SYNC_USER_DATA, builder));
    }

    /**
     * 添加打理奖励
     * @param property
     */
    public synchronized void addAutoReward(Property property) {
        this.autoReward.addProperty(property);
    }

    /**
     * 获取打理奖励
     * @return
     */
    public Property getAutoReward() {
        return this.autoReward;
    }

    /**
     * 清空打理奖励
     */
    public synchronized void clearAutoReward() {
        this.autoReward = new Property();
    }

    /**
     * 获取玩家魂力加成
     * @return
     */
    public int getPowerAddRate() {
        int addRate = 0;
        //商会船只加成
        addRate += this.getUnion().getPowerAddRate();
        //其他加成
        return addRate;
    }

    /**
     * 获取战力-加成后的
     * @return
     */
    public long getPower() {
        int addRate = this.getPowerAddRate();
        long basePower = this.userData.getPower();
        long addPower = BigDecimal.valueOf(basePower).multiply(BigDecimal.valueOf(addRate).divide(BigDecimal.valueOf(1000), 8,  RoundingMode.UP)).setScale(0, RoundingMode.CEILING).longValue();
        return basePower + addPower;
    }

    /**
     * 获取战力-算buff的
     * @return
     */
    public long getBattlePower() {
        //获取战力
        long power = this.getPower();
        //buff触发：战力加成
        int addPowerRate = this.triggerBuffAddDamage();
        if (addPowerRate > 0) {
            BigDecimal addPowerRateBig = BigDecimal.valueOf(addPowerRate).divide(BigDecimal.valueOf(1000), 8,  RoundingMode.UP);
            power = BigDecimal.valueOf(power).multiply(addPowerRateBig).setScale(0, RoundingMode.CEILING).longValue();
        }
        return power;
    }

    /**
     * 获取战力-附带邀请玩家战力
     * @param inviteUserList
     * @return
     */
    public long getPowerWithInviteUsers(List<CrossHsIslandUser> inviteUserList) {
        //获取战力
        long power = this.getBattlePower();
        //获取邀请玩家的战力
        for (CrossHsIslandUser inviteUser : inviteUserList) {
            power += inviteUser.getPower();
            //扣除可邀请次数
            inviteUser.costICanPveInviteNum();
        }
        return power;
    }

    /**
     * 获取PVE积分
     * @param monsterData
     * @param damage
     * @return
     */
    public long getPveAddScore(HsIslandMonsterData monsterData, long damage) {
        //积分比例
        BigDecimal scoreRate = BigDecimal.valueOf(damage).divide(BigDecimal.valueOf(monsterData.getAllBlood()), 8,  RoundingMode.DOWN);
        //获取总积分
        HsIslandPveConfig pveConfig = this.getConfig().getPveConfig(monsterData.getMonsterId());
        BigDecimal addScore = BigDecimal.valueOf(pveConfig.getScore()).multiply(scoreRate);
        return addScore.setScale(0, RoundingMode.CEILING).longValue();
    }

    /**
     * monster战斗
     * @param battleField
     * @param inviteUserList
     * @return
     */
    public HsIslandBattleResult battleMonster(CrossHsIslandBattleField battleField, List<CrossHsIslandUser> inviteUserList) throws BusinessException {
        //获取战力
        long power = this.getPowerWithInviteUsers(inviteUserList);
        //伤害
        long damage;
        boolean winFlag;
        if (power >= battleField.getMonsterData().getBlood()) {
            damage = battleField.getMonsterData().getBlood();
            winFlag = true;
        } else {
            damage = power;
            winFlag = false;
        }
        // 处理一下怪掉血
        battleField.getMonsterData().setReBlood(battleField.getMonsterData().getReBlood() + damage);
        // 记录下伤害信息
        CrossHsIslandBattleFieldDamage battleFieldDamage = getActivity().getBattleFieldDamageNewIfNull(battleField.getBattleFieldId(), battleField.getMonsterData().getMonsterId(), battleField.getEnemyType());
        battleFieldDamage.addDamage(this.userData.getUnionId(), this.userData.getUserId(), damage);

        //战斗结果
        HsIslandBattleResult battleResult = new HsIslandBattleResult();
        battleResult.setWinFlag(winFlag);
        battleResult.setDamage(damage);

        // 设置下当前攻击时间
        if (battleField.getEnemyType() == ENEMY_BOSS) {
            this.getUserData().setLastAttackBossTime(System.currentTimeMillis());
        } else if (battleField.getEnemyType() == ENEMY_MASTER) {
            this.getUserData().setLastAttackMonsterTime(System.currentTimeMillis());
        }
        return battleResult;
    }

    /**
     * pvp
     * @param pvpUserList
     * @return
     */
    public HsIslandPvpBattleResult pvp(List<CrossHsIslandUser> pvpUserList, HsIslandEventData event) {
        //获取战力
        long power = this.getBattlePower();
        boolean winFlag = false;
        int winNum = 0;
        for (CrossHsIslandUser pvpUser : pvpUserList) {
            if (power >= pvpUser.getPower()) {
                winFlag = true;
                winNum++;
            } else {
                //输一个就退出战斗
                break;
            }
        }
        HsIslandPvpBattleResult result = new HsIslandPvpBattleResult();
        result.setWinFlag(winFlag);
        result.setWinNum(winNum);
        //基础积分
        long score = this.getConfig().HSISLAND_PVP_BASIS_SCORE;
        int scoreMul = this.getConfig().getPvpScoreRate(winNum);
        //基础奖励
        Property baseReward = PropertyHelper.parseNewStringToProperty(this.getConfig().HSISLAND_PVP_BASIS_REWARD);
        //连胜奖励
        Property moreWinReward = null;
        HsIslandDuelConfig duelConfig = this.getConfig().getWinNumDuelConfigMap().get(winNum);
        if (duelConfig != null) {
            //连胜奖励
            moreWinReward = PropertyHelper.parseNewStringToProperty(duelConfig.getReward());
            //连胜积分加成
            BigDecimal scoreAddRateBig = BigDecimal.valueOf(scoreMul).divide(BigDecimal.valueOf(1000), 8,  RoundingMode.DOWN);
            score = BigDecimal.valueOf(score).multiply(scoreAddRateBig).setScale(0, RoundingMode.CEILING).longValue();
        }
        //奖励
        HsIslandReward hsIslandReward = this.createReward(score, baseReward, moreWinReward, event);
        result.setHsIslandReward(hsIslandReward);
        return result;
    }

    /**
     * 处理事件-2选1
     * @param event
     * @param index
     * @return
     */
    public HsIslandReward doChoose(HsIslandEventData event, int index) {
        HsIslandChooseConfig chooseConfig = this.getConfig().getChooseConfig(event.getChooseConfigId());
        //判断是正确还是错误
        int type = chooseConfig.getTypeByIndex(index);
        String reward;
        long score;
        if (type >= 1) {
            reward = chooseConfig.getTrueReward();
            score = this.getConfig().HSISLAND_CHOOSE_SCORE_PARAM.get(0);
        } else {
            reward = chooseConfig.getErrorReward();
            score = this.getConfig().HSISLAND_CHOOSE_SCORE_PARAM.get(1);
        }
        //奖励
        Property rewardProp = PropertyHelper.parseNewStringToProperty(reward);
        //奖励数据
        return this.createReward(score, rewardProp, null, event);
    }

    /**
     * 处理事件-遗迹藏宝
     * @param event
     * @param index
     * @return
     */
    public HsIslandReward doRelic(HsIslandEventData event, int index) {
        Map<Integer, HsIslandRelicConfig> relicConfigMap = this.getConfig().getRelicConfigMap();
        //池子
        Map<Integer, Integer> weightMap = new HashMap<>();
        for (HsIslandReceiveRelicRewardData rewardData : event.getReceiveRelicRewardMap().values()) {
            if (rewardData.getReceiveFlag() == HsIslandYnFlagEnum.NOT.getType()) {
                HsIslandRelicConfig relicConfig = relicConfigMap.get(rewardData.getRelicConfigId());
                weightMap.put(relicConfig.getId(), relicConfig.getWeight());
            }
        }
        int relicConfigId = RandomHelper.getRandomKeyByWeight(weightMap);
        //获取奖励
        HsIslandReceiveRelicRewardData data = event.getReceiveRelicReward(relicConfigId);
        data.setIndex(index);
        data.setReceiveFlag(HsIslandYnFlagEnum.YES.getType());
        event.setUpdateOption();
        //奖励
        Property reward = PropertyHelper.parseStringToProperty(data.getReward());
        HsIslandReward hsIslandReward = this.createReward(0, reward, null, event);
        //个人日志-遗迹藏宝事件，获得任意奖励
        HsIslandUserLog log = new HsIslandUserLog();
        log.setType(HsIslandUserLogTypeEnum.USER_LOG_TYPE_5.getType());
        log.setReward(hsIslandReward);
        log.setTime(System.currentTimeMillis());
        this.addUserLog(log);
        //返回
        return hsIslandReward;
    }

    /**
     * 创建奖励数据
     * @param score
     * @param reward
     * @param moreWinReward
     * @param event
     * @return
     */
    public HsIslandReward createReward(long score, Property reward, Property moreWinReward, HsIslandEventData event) {
        int rewardAddRate = 0;
        int scoreAddRate = 0;
        //奖励加成
        if ((reward != null && !reward.isNothing()) || (moreWinReward != null && !moreWinReward.isNothing())) {
            //触发buff
            rewardAddRate = this.triggerBuffAddReward(event);
            if (rewardAddRate > 0) {
                int countRewardMul = (int) Math.ceil((double) rewardAddRate / 1000);//向上取整
                if (reward != null) {
                    reward.goodCountMultiNum(countRewardMul);
                }
                if (moreWinReward != null) {
                    moreWinReward.goodCountMultiNum(countRewardMul);
                }
            }
        }
        //积分加成
        if (score > 0) {
            //触发buff
            scoreAddRate = this.triggerBuffAddScore(event);
            if (scoreAddRate > 0) {
                BigDecimal scoreAddRateBig = BigDecimal.valueOf(scoreAddRate).divide(BigDecimal.valueOf(1000), 8,  RoundingMode.DOWN);
                score = BigDecimal.valueOf(score).multiply(scoreAddRateBig).setScale(0, RoundingMode.CEILING).longValue();
            }
        }
        //返回
        HsIslandReward hsIslandReward = new HsIslandReward();
        hsIslandReward.setScore(score);
        hsIslandReward.setReward(reward);
        hsIslandReward.setMoreWinReward(moreWinReward);
        hsIslandReward.setScoreAddRate(scoreAddRate);
        hsIslandReward.setRewardAddRate(rewardAddRate);
        return hsIslandReward;
    }

    /**
     * 添加个人日志
     * @param log
     */
    public void addUserLog(HsIslandUserLog log) {
        this.userLogList.add(log);
    }

    /**
     * 获取个人日志
     * @return
     */
    public FixSizeLinkedList<HsIslandUserLog> getUserLogList() {
        return this.userLogList;
    }

    /*****************************************buff处理****************************************/

    /**
     * 添加BUFF
     * @param buffConfig
     */
    public void addBuff(HsIslandBuffConfig buffConfig) {
        this.userData.addBuff(buffConfig.getId(), buffConfig.getTimes());
        //日志
        HsIslandBuffData buffData = this.userData.getBuff(buffConfig.getId());
        LogCrossHsIslandBuff log = new LogCrossHsIslandBuff(
                this.userData.getActivityId(),
                this.userData.getGroupId(),
                this.userData.getUnionId(),
                this.userData.getUserId(),
                buffConfig.getId(),
                HsIslandLogBuffTypeEnum.GET.getType(),
                buffConfig.getTimes(),
                buffData.getTimes()
        );
        CrossAutoLogMgr.add(log);
    }

    /**
     * buff减少次数
     * @param buffData
     * @return
     */
    public synchronized boolean buffReTimes(HsIslandBuffData buffData) {
        if (buffData == null || buffData.getTimes() <= 0) {
            return false;
        }
        buffData.reTimes();
        //日志
        LogCrossHsIslandBuff log = new LogCrossHsIslandBuff(
                this.userData.getActivityId(),
                this.userData.getGroupId(),
                this.userData.getUnionId(),
                this.userData.getUserId(),
                buffData.getBuffId(),
                HsIslandLogBuffTypeEnum.USE.getType(),
                1,
                buffData.getTimes()
        );
        CrossAutoLogMgr.add(log);
        return true;
    }

    /**
     * 获取BUFF
     * @param buffId
     * @return
     */
    public HsIslandBuffData getBuff(int buffId) {
        return this.userData.getBuff(buffId);
    }

    /**
     * 生效BUFF-事件奖励翻倍
     * @return
     */
    public int triggerBuffAddReward(HsIslandEventData eventData) {
        if (eventData != null && eventData.getUserId() == this.userData.getUserId() && eventData.getBuffIds().contains(HsIslandBuffIdEnum.EVENT_REWARD_ADD.getType())) {
            //读取配置
            HsIslandBuffConfig buffConfig = this.getConfig().getBuffConfig(HsIslandBuffIdEnum.EVENT_REWARD_ADD.getType());
            if (buffConfig != null) {
                return buffConfig.getParamList().get(0);
            }
        }
        return 0;
    }

    /**
     * 生效BUFF-事件积分翻倍
     * @return
     */
    public int triggerBuffAddScore(HsIslandEventData eventData) {
        if (eventData != null && eventData.getUserId() == this.userData.getUserId() && eventData.getBuffIds().contains(HsIslandBuffIdEnum.EVENT_SCORE_ADD.getType())) {
            //读取配置
            HsIslandBuffConfig buffConfig = this.getConfig().getBuffConfig(HsIslandBuffIdEnum.EVENT_SCORE_ADD.getType());
            if (buffConfig != null) {
                return buffConfig.getParamList().get(2);
            }
        }
        return 0;
    }

    /**
     * 生效BUFF-事件伤害翻倍
     * @return
     */
    public int triggerBuffAddDamage() {
        HsIslandBuffData buffData = this.getBuff(HsIslandBuffIdEnum.EVENT_DAMAGE_ADD.getType());
        //buff次数减少
        boolean reFlag = this.buffReTimes(buffData);
        if (reFlag) {
            //读取配置
            HsIslandBuffConfig buffConfig = this.getConfig().getBuffConfig(buffData.getBuffId());
            if (buffConfig != null) {
                return buffConfig.getParamList().get(1);
            }
        }
        return 0;
    }

    /**
     * 生效BUFF-探索不消耗体力
     * @param reFlag 是否减少次数
     * @return
     */
    public boolean triggerBuffExploreNotEnergy(boolean reFlag) {
        HsIslandBuffData buffData = this.getBuff(HsIslandBuffIdEnum.EXPLORE_NOT_ENERGY.getType());
        if (buffData != null && buffData.getTimes() > 0) {
            //读取配置
            HsIslandBuffConfig buffConfig = this.getConfig().getBuffConfig(buffData.getBuffId());
            if (buffConfig != null) {
                //buff次数减少
                if (reFlag) {
                    this.buffReTimes(buffData);
                }
                return true;
            }
        }
        return false;
    }

    /**
     * 解锁形象
     * @param imageId
     */
    public void addUnlockImage(int imageId) {
        this.userData.addUnlockedImageId(imageId);
        //日志
        LogCrossHsIslandImageUnlock log = new LogCrossHsIslandImageUnlock(
                this.userData.getActivityId(),
                this.userData.getGroupId(),
                this.userData.getUserId(),
                imageId
        );
        CrossAutoLogMgr.add(log);
    }

    /**
     * 解锁打理形象
     * @throws BusinessException
     */
    public void unlockAutoImage() throws BusinessException {
        //判断解锁条件是否满足
        int minScore = this.getConfig().HSISLAND_FAST_FUNCTION_OPEN_COND;
        if (this.getUserData().getScore() < minScore) {
            throw new BusinessException(GameErrorCode.E_HS_ISLAND_UNLOCK_AUTO_CON_NOT_ENOUGH);
        }
        //形象ID
        int autoImageId = HsIslandImageIdEnum.IMAGE_AUTO.getType();
        //判断是否解锁过
        Set<Integer> unlockedImageIds = this.getUserData().getUnlockedImageIds();
        if (unlockedImageIds.contains(autoImageId)) {
            throw new BusinessException(GameErrorCode.E_HS_ISLAND_IMAGE_UNLOCKED);
        }
        //解锁
        this.addUnlockImage(autoImageId);
    }

    /**
     * 使用形象
     * @param imageId
     * @throws BusinessException
     */
    public void useImage(int imageId) throws BusinessException {
        Set<Integer> unlockedImageIds = this.getUserData().getUnlockedImageIds();
        //形象ID是否合法
        if (!HsIslandImageIdEnum.checkImageId(imageId)) {
            throw new BusinessException(GameErrorCode.E_HS_ISLAND_IMAGE_ID_ERROR);
        }
        //判断形象是否解锁
        if (!unlockedImageIds.contains(imageId)) {
            throw new BusinessException(GameErrorCode.E_HS_ISLAND_UNLOCK_AUTO_CON_NOT_ENOUGH);
        }
        this.userData.setImageId(imageId);
    }

    /**
     * 解锁形象，补发积分
     */
    public synchronized void unlockImageBfScore() {
        //判断形象是否已经解锁过
        if (this.userData.getUnlockedImageIds().contains(HsIslandImageIdEnum.IMAGE_ADD_SCORE.getType())) {
            return;
        }
        //需求变更，不补发积分
//        long score = this.userData.getScore();
//        long addRate = this.getImageAddScoreRate();
//        //计算一下要补发多少积分
//        long bfScore = BigDecimal.valueOf(score).multiply(BigDecimal.valueOf(addRate).divide(BigDecimal.valueOf(1000), 8,  RoundingMode.UP)).setScale(0, RoundingMode.CEILING).longValue();
//        CrossHsIslandActivityMgr.getLogger().info("海神岛-解锁形象，补发积分：{},{}", this.userData.getUserId(), bfScore);
//        //加上积分
//        this.addScore(bfScore);
        //设置形象解锁
        this.addUnlockImage(HsIslandImageIdEnum.IMAGE_ADD_SCORE.getType());
    }

    /**
     * 进入战场
     * @param battleFieldId
     */
    public void enterBattleField(long battleFieldId) {
        this.userData.setBattleFieldId(battleFieldId);
        // 攻击时间重置下,圣柱不重置
        this.userData.setLastAttackMonsterTime(0);
    }

    /**
     * 离开战场
     */
    public void leaveBattleField() {
        this.userData.setBattleFieldId(0);
    }


    /**
     * 获取pvp精力
     */
    public long getPvpEnergy() {
        return this.userData.getPvpEnergy();
    }

    /**
     * 是否处于调息状态
     *
     * @return
     */
    public boolean isPvpRest() {
        if (this.getUserData().getPvpEnergy() != 0 || this.getUserData().getPvpEnergyLastTime() == 0) {
            return false;
        }
        if (System.currentTimeMillis() - this.getUserData().getPvpEnergyLastTime() >= getConfig().HSISLAND_HOLY_PILLARS_RECOVER_TIME * DateHelper.SECOND_MILLIONS) {
            // 重置一下精力
            this.resetPvpEnergy();
        }
        return this.getUserData().getPvpEnergy() <= 0;
    }

    /**
     * 重置精力值
     */
    public void resetPvpEnergy() {
        this.getUserData().setPvpEnergy(this.getConfig().getMaxPvpEnergy(this.userData.getFloorId()));
        this.getUserData().setPvpEnergyLastTime(0);
    }

    /**
     * 扣除精力值
     */
    public void reducePvpEnergy(int pvpEnergy) {
        this.getUserData().setPvpEnergy(Math.max(0, this.getUserData().getPvpEnergy() - pvpEnergy));

        // 进入调息状态
        if (this.getUserData().getPvpEnergy() == 0) {
            // 设置下当前的时间
            this.getUserData().setPvpEnergyLastTime(System.currentTimeMillis());
        }
    }

    /**
     * 更新活跃时间
     */
    public void updateActiveTime() {
        this.userData.setActiveTime(System.currentTimeMillis());
    }

    /**
     * 校验攻击魂力限制
     *
     * @param power
     */
    public boolean checkAttackPlayerPowerLimit(long power) {
        // 我的攻击下限
        long powerDown = BigDecimal.valueOf(this.getPower()).multiply(BigDecimal.valueOf(this.getConfig().HSISLAND_HOLY_PILLARS_ATTACK_PARAM.get(0))).divide(BigDecimal.valueOf(1000), 0, RoundingMode.DOWN).longValue();
        long powerUp = BigDecimal.valueOf(this.getPower()).multiply(BigDecimal.valueOf(this.getConfig().HSISLAND_HOLY_PILLARS_ATTACK_PARAM.get(1))).divide(BigDecimal.valueOf(1000), 0, RoundingMode.DOWN).longValue();
        return power >= powerDown && power <= powerUp;
    }

    /**
     * 获取buff字符串,用于日志（buffid=数量;buffid=数量）
     * @return
     */
    public String getBuffStr() {
        Property buffProp = new Property();
        for (HsIslandBuffData buffData : this.userData.getBuffMap().values()) {
            buffProp.addProperty(buffData.getBuffId(), buffData.getTimes());
        }
        return PropertyHelper.parsePropertyToString(buffProp);
    }

    /**
     * 事件挂载上buff
     * @param eventData
     */
    public void eventAddBuff(HsIslandEventData eventData) {
        //事件配置
        HsIslandEventConfig eventConfig = this.getConfig().getEventConfig(eventData.getEventId());
        List<Integer> buffIds = eventConfig.getCanWorkBuffList();
        for (int buffId : buffIds) {
            //获取BUFF
            HsIslandBuffData buffData = this.getBuff(buffId);
            boolean reFlag = this.buffReTimes(buffData);
            if (reFlag) {
                eventData.addBuffId(buffId);
            }
        }
    }

    /**
     * 添加捐献次数
     * @param donateNum
     */
    public synchronized void addDonateNum(long donateNum) {
        this.userData.setDonateNum(this.userData.getDonateNum() + donateNum);
    }

    /**
     * 新海域红点
     * @return
     */
    public boolean getNewFloorRedDot() {
        CrossHsIslandUnion union = this.getUnion();
        if (union != null) {
            return union.getUnionData().getMaxFloorId() > this.userData.getFloorId();
        }
        return false;
    }

    /**
     * 获取可领取宝箱红点
     * @return
     */
    public boolean getBoxRewardRedDot() {
        //获取商会
        CrossHsIslandUnion union = this.getUnion();
        if (union != null) {
            //获取海域宝箱
            for (CrossHsIslandFloor floor : union.getFloorMap().values()) {
                if (this.userData.getFloorId() >= floor.getFloorData().getFloorId()) {
                    if (floor.getFloorData().getBoxFindUserId() > 0) {
                        //剩余宝箱数量
                        int residueNum = floor.getBoxAllNum() - floor.getBoxReceivedNum();
                        if (residueNum <= 0) {
                            continue;
                        }
                        //获取玩家可领取宝箱次数
                        int canOpenNum = floor.getBoxUserAllNum(this.userData.getUserId()) - floor.getBoxUserReceivedNum(this.userData.getUserId());
                        if (canOpenNum > 0) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    /**
     * 获取协助未领取奖励红点
     * @return
     */
    public boolean getHelpRewardRedDot() {
        return this.pveRewardNum > 0;
    }

    /**
     * boss奖励红点
     *
     * @return
     */
    public boolean getBossRewardRedDot() {
        long startTime = System.currentTimeMillis();
        CrossHsIslandActivityMgr.getLogger().info("海神岛-红点-boss1:{}", System.currentTimeMillis() - startTime);
        CrossHsIslandActivity activity = getActivity();
        if (activity == null) {
            return false;
        }
        // 当前击杀的boss信息
        for (CrossHsIslandKillBossRecord killBossRecord : activity.getKillBossRecordMap().values()) {
            long battleFieldId = killBossRecord.getKillBossRecord().getBattleFieldId();
            if (this.userData.getHadRewardBattleFieldIdList().contains(battleFieldId)) {
                // 已领过了
                continue;
            }
            // 算下我商会的排名
            CrossHsIslandBattleFieldDamage myUnionBattleFieldDamage = activity.getBattleFieldDamage(battleFieldId);
            int myUnionRank = -1;
            if (myUnionBattleFieldDamage != null) {
                CrossHsIslandRankListModel unionDamageRankModel = myUnionBattleFieldDamage.getUnionDamageRankModel();
                if (unionDamageRankModel != null) {
                    myUnionRank = unionDamageRankModel.getMyRank(this.userData.getUnionId());
                }
                // 判断一下有没有奖励
                Property bossReward = activity.getConfig().getBossReward(myUnionRank);
                if (bossReward == null || bossReward.isNothing()) {
                    myUnionRank = -1;
                }
            }
            if (myUnionRank != -1) {
                // 有一个就可以
                return true;
            }
        }
        CrossHsIslandActivityMgr.getLogger().info("海神岛-红点-boss2:{}", System.currentTimeMillis() - startTime);
        return false;
    }

    /**
     * 同步红点数据
     */
    public void syncRedDot() {
        HsIslandProto.HsIslandSyncRedDotMsg.Builder msg = CrossHsIslandActivityPb.buildHsIslandSyncRedDotMsg(
                this.getHelpRewardRedDot(),
                this.getBossRewardRedDot(),
                this.getBoxRewardRedDot(),
                this.getNewFloorRedDot()
        );
        MessageHelper.sendPacket(this.userData.getServerId(), this.userData.getUserId(), YanQuMessageUtils.buildMessage(Protocol.U_HS_ISLAND_SYNC_RED_DOT, msg));
    }

    /**
     * 同步红点数据
     */
    public void syncRedDotForBossReward() {
        HsIslandProto.HsIslandSyncRedDotMsg.Builder msg = CrossHsIslandActivityPb.buildHsIslandSyncRedDotMsg(
                this.getHelpRewardRedDot(),
                true,
                this.getBoxRewardRedDot(),
                this.getNewFloorRedDot()
        );
        MessageHelper.sendPacket(this.userData.getServerId(), this.userData.getUserId(), YanQuMessageUtils.buildMessage(Protocol.U_HS_ISLAND_SYNC_RED_DOT, msg));
    }

    /**
     * 增加捐献双倍次数
     * @param num
     */
    public synchronized void addDUsableDonateNum(int num) {
        this.userData.setDUsableDonateNum(this.userData.getDUsableDonateNum() + num);
    }
}
